/**
 * All rights Reserved, Designed By www.tydic.com
 * @Title: EasyPaySignUtil.java
 * @Package: com.example.down
 * @Description:
 * @author: wangtao
 * @date: 2019年10月15日 下午3:06:54
 */
package com.hlkj.pay.app.merchant.ext.impl.dffpay.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.hlkj.pay.app.merchant.ext.impl.dffpay.dto.DffPayConfig;
import com.hlkj.pay.util.SignUtils;
import org.springframework.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.*;

/**
 * @ClassName: EasyPaySignUtil
 * @Description:
 * @author: wangtao
 * @date: 2019年10月15日 下午3:06:54
 */
public class DffPaySignUtil {

	/**
	 * 使用商户的私钥进行加签
	 *
	 * @param signContent: 签名数据，注意这里仅仅是文档中data字段的内容
	 * @return java.lang.String 签名
	 */
	public static String sign(String signContent, String signKey) throws Exception {
//		String reqBodyMd5 = getReqBodyMd5(dataJson.getJSONObject("reqBody"));
//		String signContent = JSON.toJSONString(dataJson.getJSONObject("reqHeader"), SerializerFeature.MapSortField) + reqBodyMd5;
		return DffPayRsaUtil.signBySHA256WithRSA(signContent, signKey);
	}

	/**
	 * @param dataObj 数据对象 不能都为空
	 * @return 签名排序字符串
	 */
	public static String getReqBodyMd5(JSONObject dataObj) {
		if (dataObj.isEmpty()) {
			return SignUtils.md5("{}").toUpperCase();
		} else {
			String body = JSON.toJSONString(dataObj, SerializerFeature.MapSortField);
			// 将MD5字节数组转换成十六进制字符串
			StringBuilder hexString = new StringBuilder();
			try {
				// 获取MD5算法的MessageDigest对象
				MessageDigest md = MessageDigest.getInstance("MD5");
				// 计算MD5签名
				byte[] md5Bytes = md.digest(body.getBytes());
				for (byte b : md5Bytes) {
					hexString.append(String.format("%02x", b));
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			return hexString.toString().toUpperCase();
		}
	}

	public static boolean verify(JSONObject dataJson, DffPayConfig dffPayConfig) {
		String reqBodyMd5 = getReqBodyMd5(dataJson.getJSONObject("reqBody"));
		String signContent = JSON.toJSONString(dataJson.getJSONObject("reqHeader"), SerializerFeature.MapSortField) + reqBodyMd5;
		return DffPayRsaUtil.verifyBySHA256WithRSA(signContent, dataJson.getString("reqSign"), dffPayConfig.getPublicKey());
	}

	/**
	 * MD5签名
	 *
	 * @param request 请求内容不包含sign
	 * @param signKey 签名key
	 */
	public static String md5Sign(Map<String, String> request, String signKey) {
		Set<String> keySet = request.keySet();
		TreeSet<String> treeSet = new TreeSet<>(keySet);
		StringBuilder stringBuilder = new StringBuilder();
		for (String key : treeSet) {
			if (!"MAC".equals(key) && StringUtils.hasText(request.get(key))) {
				stringBuilder.append(key).append("=").append(request.get(key)).append("&");
			}
		}
		stringBuilder.append("key=").append(signKey);
		// 将MD5字节数组转换成十六进制字符串
		StringBuilder hexString = new StringBuilder();
		try {
			// 获取MD5算法的MessageDigest对象
			MessageDigest md = MessageDigest.getInstance("MD5");
			// 计算MD5签名
			byte[] md5Bytes = md.digest(stringBuilder.toString().getBytes());
			for (byte b : md5Bytes) {
				hexString.append(String.format("%02x", b));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return hexString.toString().toUpperCase();
	}

	/**
	 * MD5签名 拆分专用
	 *
	 * @param request 请求内容不包含sign
	 * @param signKey 签名key
	 */
	public static String md5SignSplit(Map<String, String> request, String signKey) {
		List<String> keys = List.of("appId", "backUrl", "clientCode", "merTrace", "messageType", "operaTrace", "operType", "playType", "pubName", "tradeType", "version");
		StringBuilder stringBuilder = new StringBuilder();

		for (String key : keys) {
			if (!"MAC".equals(key) && StringUtils.hasText(request.get(key))) {
				stringBuilder.append(key).append("=").append(request.get(key)).append("&");
			}
		}
		stringBuilder.append("key=").append(signKey);
		// 将MD5字节数组转换成十六进制字符串
		StringBuilder hexString = new StringBuilder();
		try {
			// 获取MD5算法的MessageDigest对象
			MessageDigest md = MessageDigest.getInstance("MD5");
			// 计算MD5签名
			byte[] md5Bytes = md.digest(stringBuilder.toString().getBytes());
			for (byte b : md5Bytes) {
				hexString.append(String.format("%02x", b));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return hexString.toString().toUpperCase();
	}

	public static void main(String[] args) throws Exception {
		Map<String, String> m = new HashMap<>();
		m.put("clientCode", "48310004");
		m.put("merTrace", "62a6f4f23e10af0b5dbd59ca");
		m.put("messageType", "SENDZFBORWX");
		m.put("operaTrace", "QJCF9000000433951559");
		m.put("operType", "add");
		m.put("playType", "Q2");
		m.put("tradeType", "Q");
		m.put("version", "1.0");

		System.out.println(md5SignSplit(m, "eGGlh0NHurHFNwHB")) ;
	}
}
